<?php
namespace app\admin\controller;

use bigDream\thinkJump\Jump;
use think\facade\App;
use think\facade\Config;
use think\facade\Filesystem;
use think\facade\Request;
use think\facade\Validate;

class FileManager {
    /**
     * 文件列表
     * @return \think\response\View
     */
    public function index()
    {
        $disk = Filesystem::disk('wampserver');

        $path = Request::param('path', '');

        $list = $disk->listContents($path);

        $breadcrumb = [];
        $temp = '';
        foreach (explode(DIRECTORY_SEPARATOR, rtrim($path, DIRECTORY_SEPARATOR)) as $item) {
            $temp .= $item . DIRECTORY_SEPARATOR;
            $breadcrumb[] = [
                'name' => $item,
                'path' => $temp,
                'url'  => url('', ['path' => $temp]),
            ];
        }

        return view('', [
            'list'       => $list,
            'path'       => $path,
            'breadcrumb' => $breadcrumb,
        ]);
    }

    /**
     * 删除
     * @return \think\response\Json
     */
    public function delete()
    {
        $disk = Filesystem::disk('wampserver');

        try {
            foreach (Request::param('dir/a', []) as $path) {
                $disk->deleteDirectory($path);
            }
            foreach (Request::param('file/a', []) as $path) {
                $disk->delete($path);
            }
        } catch (\Exception $e) {
            return json([
                'code' => 1,
                'msg'  => $e->getMessage(),
            ]);
        }

        return json([
            'code' => 0,
            'msg'  => '删除成功',
        ]);
    }

    /**
     * 重命名
     */
    public function rename()
    {
        $data = Request::only(['path', 'old', 'new']);

        $validate = Validate::rule([
            'path' => ['require'],
            'old'  => ['require'],
            'new'  => ['require'],
        ]);
        if (!$validate->check($data)) {
            Jump::error($validate->getError());
        }

        $disk = Filesystem::disk('wampserver');

        $path = rtrim($data['path'], DIRECTORY_SEPARATOR);
        if ('' != $path && !$disk->fileExists($path)) {
            Jump::error('路径不存在：' . $path);
        }

        if ($data['old'] == $data['new']) {
            Jump::error('名称未改变');
        }

        $old = $path . DIRECTORY_SEPARATOR . $data['old'];
        if (!$disk->has($old)) {
            Jump::error('旧路径不存在');
        }

        $new = $path . DIRECTORY_SEPARATOR . $data['new'];
        if ($disk->has($new)) {
            Jump::error('新路径已存在');
        }

        if ($disk->rename($old, $new)) {
            Jump::success('重命名成功');
        } else {
            Jump::error('重命名失败');
        }
    }

    /**
     * 文件上传
     * @return \think\response\Json
     */
    public function upload()
    {
        try {
            $file = Request::file('file');
            if (null === $file) {
                throw new \Exception('请上传文件', UPLOAD_ERR_NO_FILE);
            }

            $data = Request::only(['path', 'filename' => $file->getOriginalName(), 'fileSize', 'blockNum', 'blockNo']);
            $data['file'] = $file;

            $validate = Validate::rule([
                'path'      => [],
                'filename'  => ['require'],
                'blockNum'  => ['require', 'integer'],
                'blockNo'   => ['require', 'integer'],
                'file'      => ['require', 'fileExt' => Config::get('filesystem.allowFileExt')],
                'fileSize'  => ['require'],
            ]);
            if (!$validate->check($data)) {
                throw new \Exception($validate->getError());
            }

            $disk = Filesystem::disk('wampserver');

            $data['path'] = rtrim($data['path'], DIRECTORY_SEPARATOR);
            if ('' != $data['path'] && !$disk->has($data['path'])) {
                Jump::error('路径不存在：' . $data['path']);
            }

            if ($disk->fileExists($data['path'] . DIRECTORY_SEPARATOR . $data['filename'])) {
                throw new \Exception('文件已存在');
            }

            $filenameMd5 = md5($data['filename']);
            $runtime = Filesystem::disk('runtime');

            $name = $filenameMd5 . '.' . $file->extension() . '_' . sprintf('%04d', $data['blockNo']);
            $filepath = $runtime->putFileAs('temp', $file, $name);
            $result = $runtime->getMetadata($filepath);

            if ($data['blockNum'] == $data['blockNo']) {
                $list = $runtime->listContents('temp');
                $temp = tmpfile();
                if (false === $temp) throw new \Exception('创建临时文件失败');
                foreach ($list as $item) {
                    if ($item['filename'] != $filenameMd5) continue;
                    $content = $runtime->readAndDelete($item['path']);
                    if (false === $content) throw new \Exception('读取并删除临时文件失败：' . $item['path']);
                    fwrite($temp, $content);
                }

                $filepath = $data['path'] . DIRECTORY_SEPARATOR . $data['filename'];
                if (!$disk->putStream($filepath, $temp)) {
                    throw new \Exception('写入文件失败：' . $filepath);
                }
                $result = $disk->getMetadata($filepath);

                if ($result['size'] != $data['fileSize']) {
                    throw new \Exception('文件损坏：合成后的文件大小与上传的文件不符');
                }
            }
        } catch (\Exception $e) {
            return json([
                'code' => 1,
                'msg'  => $e->getMessage(),
            ]);
        }

        return json([
            'code' => 0,
            'msg'  => '上传成功',
            'data' => $result,
        ]);
    }
}